package Java8新特性;

import org.junit.Test;

import java.util.Optional;

/*
    Optional<T> 类(java.util.Optional) 是一个容器类,它可以保存类型 T 的值,代表这个值存在,或者仅仅保存null,表示这个值不存在,原来用 null 表示一个值不存在,现在 Optional 可以更好的表达这个概念,并且可以避免空指针异常
    Optional类的Javadoc描述如下:这是一个可以为null的容器对象,如果值存在则isPresent()方法会返回true,调用get()方法会返回该对象
    Optional提供很多有用的方法,这样就不用显式进行空值检测
 */
public class Optional08 {

    /*
       创建Optional类对象的方法
         Optional.of(T t):通过工厂方法创建Optional类,创建对象时传入的参数不能为null,如果传入参数为null,则抛出NullPointerException
         Optional.empty():创建一个空的 Optional 实例
         Optional.ofNullable(T t):t可以为null
    */
    @Test
    public void test1(){
        Optional<String> r1 = Optional.of("瑞熙科技");
        Optional<String> r2 = Optional.ofNullable(null);
        Optional<String> r3 = Optional.empty();
    }

    /*
       判断Optional容器中是否包含对象
         boolean isPresent():判断是否包含对象
         void ifPresent(Consumer<? super T> consumer):如果有值,就执行Consumer接口的实现代码,并且该值会作为参数传给它
         get():在Optional实例内调用get()返回已存在的值
     */
    @Test
    public void test3(){
        Optional<Girl> girl = Optional.ofNullable(new Girl("小红"));
        //判断是否包含对象
        System.out.println(girl.isPresent());
        //如果对象不是空的,就对执行传入的 Lambda 表达式
        girl.ifPresent(e -> e.setName("小芳"));
    }

    //orElse():如果有值则将其返回,否则返回指定的其它值(如果值不为null,orElse方法返回Optional实例的值,如果为null,返回传入的消息)
    @Test
    public void test5(){
        Optional<Girl> girl = Optional.ofNullable(null);
        System.out.println(girl.orElse(new Girl("小芳")));
    }

    //orElseGet():与orElse()方法类似,区别在于orElse()传入的是默认值,orElseGet()可以接受一个lambda表达式生成默认值
    @Test
    public void test6(){
        Optional<Girl> girl = Optional.ofNullable(null);
        Girl result = girl.orElseGet(Girl::new);
        System.out.println(result);
    }

    //orElseThrow():orElse()方法类似,与返回默认值不同,orElseThrow会抛出lambda表达式或方法生成的异常
    @Test
    public void test7(){
        Optional<Object> result = Optional.ofNullable(null);
        result.orElseThrow(() -> new RuntimeException("空指针异常"));
    }

    /*
        map():对值应用(调用)作为参数的函数,然后将返回的值包装在 Optional 中
     */
    @Test
    public void test8(){
        Optional<Girl> result = Optional.ofNullable(null);
        String name = result.map(e -> e.getName()).orElse("小芳");
        System.out.println(name);
    }

    /*
       flatMap():map()方法类似,区别在于mapping函数的返回值不同,map方法的mapping函数返回值可以是任何类型T,而flatMap方法的mapping函数必须是Optional
       flatMap()与map(Function)非常类似,区别在于传入方法的lambda表达式的返回类型
       map()方法中的lambda表达式返回值可以是任意类型,在map函数返回之前会包装为Optional
       但flatMap方法中的lambda表达式返回值必须是Optional实例
     */
    @Test
    public void test9(){
        Girl girl = new Girl("小红");
        Optional<Girl> optional = Optional.ofNullable(girl);
        Optional<String> str = optional.flatMap(e -> Optional.of(e.getName()));
        System.out.println(str);
    }

    /*
        filter():检查给定的Option值是否满足某些条件,如果满足则返回同一个Option实例,否则返回空Optional
     */
    @Test
    public void test10(){
        Optional<Girl> result = Optional.ofNullable(null);
        Optional<Girl> filter = result.filter(e -> e.getName().length() > 1);
        System.out.println(filter.isPresent());
    }

}
